/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jstyle.jstylecommon.scan;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.jstyle.jstylecommon.R;
import com.jstyle.jstylecommon.R2;
import com.jstyle.jstylecommon.filter.FilterDialog;
import com.jstyle.jstylecommon.model.ExtendedBluetoothDevice;
import com.jstyle.jstylecommon.utils.PermissionsUtil;
import com.jstyle.jstylecommon.utils.ResolveData;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import butterknife.BindView;
import butterknife.ButterKnife;


/**
 * Activity for scanning and displaying available Bluetooth LE devices.
 */
public class DeviceScanActivity extends AppCompatActivity implements FilterDialog.DeviceFilterListener, PermissionsUtil.PermissionListener {
    @BindView(R2.id.list_viewDevice)
    RecyclerView listView;
    private LeDeviceListAdapter mLeDeviceListAdapter;
    private BluetoothAdapter mBluetoothAdapter;
    private boolean mScanning;
    private Handler mHandler;
    private UUID[] serviceUuids = new UUID[]{UUID.fromString("00001809-0000-1000-8000-00805f9b34fb")};
    public static final String KEY_address = "address";
    public static final String KEY_DeviceName = "DeviceName";
    public static final String KEY_OpActivity = "KEY_OpActivity";
    public static final String KEY_Path = "KEY_Path";
    // private static UUID[] serviceUuids=new
    // UUID[]{UUID.fromString("00001950-0000-1000-8000-00805f9b34fb")};

    private static final int REQUEST_ENABLE_BT = 1;
    // Stops scanning after 10 seconds.
    private static final long SCAN_PERIOD = 10000;
    private int GPS_REQUEST_CODE = 5556;
    Class classActivity;
    Uri fileUri;
    String firmwarePath;
    private SharedPreferences sharedPreferences;
    private static final String spName = "jstyle_common";
    public static final String KEY_REMIND_fILTERNAME = "KEY_REMIND_fILTERNAME";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan_device);
        ButterKnife.bind(this);
        mHandler = new Handler();
        classActivity= (Class) getIntent().getSerializableExtra(KEY_OpActivity);
        if (!getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT)
                    .show();
            finish();
        }

        // Initializes a Bluetooth adapter. For API level 18 and above, get a
        // reference to
        // BluetoothAdapter through BluetoothManager.

        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        // Checks if Bluetooth is supported on the device.
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, R.string.error_bluetooth_not_supported,
                    Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        sharedPreferences = getSharedPreferences(spName, Activity.MODE_PRIVATE);
        filterName=sharedPreferences.getString(KEY_REMIND_fILTERNAME,"");
        mLeDeviceListAdapter = new LeDeviceListAdapter();
        RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        listView.setLayoutManager(linearLayoutManager);
        listView.setAdapter(mLeDeviceListAdapter);
        listView.addItemDecoration(dividerItemDecoration);
        mLeDeviceListAdapter.setOnItemClickListener(new LeDeviceListAdapter.onItemClickListener() {
            @Override
            public void onItemClick(int position) {
                final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
                if (device == null)
                    return;
                String name = mLeDeviceListAdapter.getName(position);
                if (mScanning) {
                    scanLeDevice(false);
                }
                Log.i(TAG, "onItemClick: "+device.getAddress());
                if(classActivity==null)return;
                final Intent intent = new Intent(DeviceScanActivity.this, classActivity);
                intent.putExtra(KEY_address, device.getAddress());
                intent.putExtra(KEY_DeviceName, name);
                if(fileUri !=null)intent.setData(fileUri);
                if(!TextUtils.isEmpty(firmwarePath))intent.putExtra(KEY_Path,firmwarePath);
                startActivity(intent);
            }
        });

        setListAdapter(mLeDeviceListAdapter);
        //Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
       // List<ExtendedBluetoothDevice> list = new ArrayList<>();
//        for (BluetoothDevice device : devices) {
//            Log.i(TAG, "onResume: " + device.getName() + " " + device.getAddress());
//            list.add(new ExtendedBluetoothDevice(device));
//        }
//        mLeDeviceListAdapter.addBondDevice(list);
        fileUri=getIntent().getData();
        firmwarePath=getIntent().getStringExtra(KEY_Path);
        PermissionsUtil.requestPermissions(this, this, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        if (!mScanning) {
            menu.findItem(R.id.menu_stop).setVisible(false);
            menu.findItem(R.id.menu_scan).setVisible(true);
            menu.findItem(R.id.menu_refresh).setActionView(null);
        } else {
            menu.findItem(R.id.menu_stop).setVisible(true);
            menu.findItem(R.id.menu_scan).setVisible(false);
            menu.findItem(R.id.menu_refresh).setActionView(
                    R.layout.actionbar_indeterminate_progress);
        }
        return true;
    }

    private static final String TAG = "DeviceScanActivity";
    String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;


    public static String assetsPath = "J1668_06_V011_3_20180326.zip";

    //public static String assetsPath = "J1638_10_ONE_V015_4_20180309.zip";

    boolean isGranted;

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.menu_scan) {
            PermissionsUtil.requestPermissions(this, this, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION);

        } else if (item.getItemId() == R.id.menu_stop) {
            scanLeDevice(false);

        } else if (item.getItemId() == R.id.menu_filter) {
            showFilterDialog();

        }

        return true;
    }

    FilterDialog filterDialog;

    private void showFilterDialog() {
        String filterName=sharedPreferences.getString(KEY_REMIND_fILTERNAME,"");
        if (filterDialog == null) {
            filterDialog = new FilterDialog(this, this);
        }

        if (!filterDialog.isShowing()) filterDialog.show();
        filterDialog.setFilterName(filterName);
//
    }

    private void changeFilter() {
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (!mBluetoothAdapter.isEnabled()) {
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }
        if (isGranted && !mScanning) scanLeDevice(true);

        // Initializes list view adapter.


    }

    private void setListAdapter(LeDeviceListAdapter mLeDeviceListAdapter) {
        listView.setAdapter(mLeDeviceListAdapter);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // User chose not to enable Bluetooth.
        if (requestCode == REQUEST_ENABLE_BT
                && resultCode == Activity.RESULT_CANCELED) {
            finish();
            return;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onPause() {
        super.onPause();
        scanLeDevice(false);


    }


    private void scanLeDevice(final boolean enable) {

        if (enable) {
            extendedBluetoothDevices.clear();
            mLeDeviceListAdapter.clear();
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    mScanning = false;
                    invalidateOptionsMenu();
                }
            }, 12000);
            mBluetoothAdapter.startLeScan(mLeScanCallback);
            //	mBluetoothAdapter.startLeScan(serviceUuids, mLeScanCallback);
            mScanning = true;

        } else {
            if (!mScanning) return;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
            mHandler.removeCallbacksAndMessages(null);
            mScanning = false;

        }
        invalidateOptionsMenu();
    }

    String filterName = "";
    int filterRssi = -100;
    private List<ExtendedBluetoothDevice> extendedBluetoothDevices = new ArrayList<>();

    private ExtendedBluetoothDevice findDevice(final BluetoothDevice device) {
        for (final ExtendedBluetoothDevice mDevice : extendedBluetoothDevices) {
            if (mDevice.matches(device)) return mDevice;
        }
        return null;
    }

    public void addDevice(BluetoothDevice device, String name, int rssi) {
        ExtendedBluetoothDevice bluetoothDevice = findDevice(device);
        if (bluetoothDevice == null) {
            extendedBluetoothDevices.add(new ExtendedBluetoothDevice(device, name, rssi));
        } else {
            bluetoothDevice.rssi = rssi;
        }
    }

    // Adapter for holding devices found through scanning.


    // Device scan callback.

    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, final int rssi,
                             final byte[] scanRecord) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(!mScanning)return;
                    String deviceName = ResolveData.decodeDeviceName(scanRecord);
                    if (TextUtils.isEmpty(deviceName))
                        deviceName = getString(R.string.unknown_device);
                    addDevice(device, deviceName, rssi);
                    Log.i(TAG, "run: "+deviceName);
                    if (TextUtils.isEmpty(filterName) || deviceName.toLowerCase().contains(filterName.toLowerCase())) {
                        if (rssi >= filterRssi) {
                            mLeDeviceListAdapter.addDevice(device, deviceName, rssi);
                        }
                    }


                }
            });
        }
    };


    @Override
    public void DeviceFilter(String name, int rssi) {
        Log.i(TAG, "DeviceFilter: " + rssi);
        filterName = name;
        filterRssi = rssi;
        sharedPreferences.edit().putString(KEY_REMIND_fILTERNAME,name).commit();
        List<ExtendedBluetoothDevice> devices = new ArrayList<>();
        for (ExtendedBluetoothDevice extendedBluetoothDevice : extendedBluetoothDevices) {
            String deviceName = extendedBluetoothDevice.name;
            int deviceRssi = extendedBluetoothDevice.rssi;
            if (TextUtils.isEmpty(filterName)) {
                if (deviceRssi > rssi) devices.add(extendedBluetoothDevice);
            } else {
                if (deviceName.toLowerCase().contains(filterName) && deviceRssi > rssi) {
                    devices.add(extendedBluetoothDevice);
                }
            }

        }
        mLeDeviceListAdapter.setDeviceList(devices);
    }

    @Override
    public void granted(String name) {
        if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(name)) {

        } else if (Manifest.permission.ACCESS_FINE_LOCATION.equals(name)) {
            if (mLeDeviceListAdapter != null) mLeDeviceListAdapter.clear();
            if (extendedBluetoothDevices != null) extendedBluetoothDevices.clear();
            if (!PermissionsUtil.isLocServiceEnable(this)) {
                showEnableGps();
                return;
            }
            isGranted = true;
            scanLeDevice(true);
        }
    }

    private void showEnableGps() {
        new AlertDialog.Builder(this).setTitle(R.string.open_gps_setting_title)
                .setMessage(R.string.open_gps_setting_content)
                //  取消选项
                .setNegativeButton(getString(R.string.access_no), null)
                //  确认选项
                .setPositiveButton(getString(R.string.access_now), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //跳转到手机原生设置页面
                        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        startActivityForResult(intent, GPS_REQUEST_CODE);
                    }
                })
                .setCancelable(false)
                .show();
    }

    @Override
    public void NeverAskAgain() {

    }

    @Override
    public void disallow(String name) {

    }
    public interface onDeviceItemClickListener{
        public void onDeviceItem(String address);
    }
}